package cn.hzc.fortess.system.service;

import cn.hzc.fortess.core.common.BizErrorEnum;
import cn.hzc.fortess.core.common.annotion.CURDLog;
import cn.hzc.fortess.core.common.exception.ServiceException;
import cn.hzc.fortess.core.shiro.ShiroKit;
import cn.hzc.fortess.system.dao.ResourceAttrDao;
import cn.hzc.fortess.system.entity.ResourceAttr;
import cn.hzc.fortess.system.vo.ResourceAttrVO;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;


@Service
public class ResourceAttrServiceImpl implements ResourceAttrService {

    @Autowired
    ResourceAttrDao resourceAttrDao;

    @Override
    public List<ResourceAttr> getMenuResourceAttrList(Integer menuId) {
        return resourceAttrDao.findMenuResourceAttrList(menuId);
    }


    private void cleanMenuIdAttrs(Integer menuId) {
        resourceAttrDao.deleteByMenuId(menuId);
    }

    private void createMenuIdAttrs(List<ResourceAttr> attrs) {
        attrs.stream().forEach(resourceAttr -> {
            resourceAttr.setId(null);
            resourceAttr.setCreateTime(new Date());
            resourceAttr.setCreateUser(ShiroKit.getUser().getAccount());
            resourceAttrDao.insert(resourceAttr);
        });
    }

    private void checkRepeat(List<ResourceAttr> attrs) {
        Set<String> codes = Sets.newHashSet();
        attrs.parallelStream().forEach(resourceAttr -> {
            codes.add(resourceAttr.getAttrCode());
        });
        if (!Objects.equals(attrs.size(), codes.size())) {
            throw new ServiceException(BizErrorEnum.CANT_REPEAT_DATA);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CURDLog("菜单页面字段编辑")
    public void save(final Integer menuId, final List<ResourceAttr> attrs) {
        if (CollectionUtils.isEmpty(attrs)) {
            this.cleanMenuIdAttrs(menuId);
            return;
        }
        //检查是否存在重复的attrcode
        checkRepeat(attrs);

        final List<ResourceAttr> menuAttrs = resourceAttrDao.findMenuResourceAttrList(menuId);
        if (CollectionUtils.isEmpty(menuAttrs)) {
            createMenuIdAttrs(attrs);
            return;
        }
        final List<Integer> deles = findDeleteIdList(menuAttrs, attrs);
        if (!CollectionUtils.isEmpty(deles)) {
            deles.stream().forEach(id -> resourceAttrDao.delete(id));
        }

        attrs.stream().forEach(resourceAttr -> {
            if (resourceAttr.getId() == null) {
                resourceAttr.setCreateTime(new Date());
                resourceAttr.setCreateUser(ShiroKit.getUser().getAccount());
                resourceAttrDao.insert(resourceAttr);
            } else {
                resourceAttr.setUpdateTime(new Date());
                resourceAttr.setUpdateUser(ShiroKit.getUser().getAccount());
                resourceAttrDao.update(resourceAttr);
            }
        });

    }

    @Override
    public List<ResourceAttrVO> getRoleResourceAttrList(Integer menuId,List<Integer> roleIds) {
        if(roleIds!=null) {
            final StringBuilder ids = new StringBuilder("");
                roleIds.parallelStream().forEach(id -> ids.append(id).append(","));
            return resourceAttrDao.findRoleResourceAttrList(menuId, ids.toString() + "0");
        }
        return resourceAttrDao.findRoleResourceAttrList(menuId, null);
    }

    private List<Integer> findDeleteIdList(final List<ResourceAttr> menuAttrs, final List<ResourceAttr> requestAttrs) {
        final AtomicReference<List<Integer>> deles = new AtomicReference(Lists.newArrayList());
        menuAttrs.parallelStream().map(ResourceAttr::getId).forEach(id -> {
                    for (ResourceAttr attr : requestAttrs) {
                        if (attr.getId() == null) {
                            return;
                        }
                        if (Objects.equals(id, attr.getId())) {
                            return;
                        }
                    }
                    deles.get().add(id);
                }
        );
        return deles.get();
    }
}
